package w83b.w83bUtilidadesComunes;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Iterator;

import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;

public abstract class W83bBaseWSInterface {

	
		
		private String urlWs; 
		
		/**
		 * 
		 * @return String URL del servicio web
		 */
		protected abstract String getWebServiceURL();
		
		/**
		 * 
		 */
		public W83bBaseWSInterface(){
			this.urlWs = this.getWebServiceURL();
		}
			
		
		/**
	     * Realiza la invocación a un servicio web dada la url, el método los nombres de los parámetros y sus valores
	     * @param method Método del servicio web que se va a invocar
	     * @param paramNames Array de nombres de los parámetros
	     * @param paramValues Array de valores de los parámetros               
	     * @return String con la respuesta del servicio web
	     * @throws W83bWSInterfaceException excepcion
	     */            
			protected  String invoke (String method, String[] paramNames, String[] paramValues) throws W83bWSInterfaceException {
	        String rtdo = "";
	        W83bClsTrazas.trazaDebug(null, "W83bBaseWSInterface[invoke " + method +"] Entra");
	        try{
	            MessageFactory mfactory = MessageFactory.newInstance();
	            SOAPMessage message = mfactory.createMessage();
	            SOAPPart soapPart = message.getSOAPPart();
	            SOAPEnvelope envelope = soapPart.getEnvelope();
	            SOAPBody body = envelope.getBody();   
	            
	            Name name = envelope.createName(method, "", "http://www.openuri.org/");
	            
	            SOAPBodyElement element = body.addBodyElement(name);
	            W83bClsTrazas.trazaDebug(null, "paramNames.length" + paramNames.length);
	            for (int i=0; i < paramNames.length && i < paramValues.length; i++) {
	                SOAPElement param = element.addChildElement(envelope.createName( paramNames[i]) );
	                param.addTextNode( paramValues[i] );
	            }         
	            SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();
	            SOAPConnection con = factory.createConnection();
	            SOAPMessage response = con.call(message, this.urlWs);  
	            if(W83bBaseWSInterface.hasFault(response)){
	            	throw new W83bWSInterfaceException("W83bBaseWSInterface[invoke " + method +"] Error: La respuesta contiene errores" ,null);
	            }
	            rtdo = W83bBaseWSInterface.getResultado(response);
	           
	        }catch(SOAPException e){
	        	throw new W83bWSInterfaceException("W83bBaseWSInterface[invoke " + method +"] Error: " + e.getMessage(),e);
	        }catch (Exception e) {
	        	throw new W83bWSInterfaceException("W83bBaseWSInterface[invoke " + method +"] Error: " + e.getMessage(),e);
			}
	        W83bClsTrazas.trazaDebug(null, "W83bBaseWSInterface[invoke " + method +"] Sale");
	        return rtdo;
	    }//Fin invoke   
			
			/**
		     * Realiza la invocación a un servicio web dada la url, el método los nombres de los parámetros y sus valores
		     * @param method Método del servicio web que se va a invocar
		     * @param paramNames Array de nombres de los parámetros
		     * @param paramValues Array de valores de los parámetros               
		     * @return String con la respuesta del servicio web
		     * @throws W83bWSInterfaceException excepcion
		     */            
		protected  String invoke (String security, String method, String[] paramNames, String[] paramValues) throws W83bWSInterfaceException {
        String rtdo = "";
        W83bClsTrazas.trazaDebug(null, "Se invoca el webService: " + method);
        W83bClsTrazas.trazaDebug(null, "paramNames.length: " + paramNames.length);
        for(int i=0; i < paramNames.length; i++){
        	 W83bClsTrazas.trazaDebug(null, "paramName YOLY2: " + paramNames[i] + " paramValue: " + paramValues[i]); 
        }
        try{
        	 MimeHeaders mimeHeaders = new MimeHeaders();
        	 mimeHeaders.addHeader("Content-Type", "text/xml");
        	
        	
            MessageFactory mfactory = MessageFactory.newInstance();
            
            StringBuffer sbSOAP = new StringBuffer("");
          

            sbSOAP.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\"http://com.ejie.x43f/X43FNSHF/\">");
            sbSOAP.append("<soapenv:Header>");
            sbSOAP.append("<n38>" + security.split("<n38>")[1].split("</n38>")[0] + "</n38>");
            sbSOAP.append("</soapenv:Header>");
            sbSOAP.append("<soapenv:Body>");
            sbSOAP.append("<ws:").append(method).append(">");
            
            for (int i=0; i < paramNames.length && i < paramValues.length; i++) {
            	 sbSOAP.append("<").append(paramNames[i]).append(">");
            	 sbSOAP.append(paramValues[i]);
            	 sbSOAP.append("</").append(paramNames[i]).append(">");
            }
            sbSOAP.append("</ws:").append(method).append(">");
            sbSOAP.append("</soapenv:Body>");
            sbSOAP.append("</soapenv:Envelope>");
            SOAPMessage message = mfactory.createMessage(mimeHeaders,new ByteArrayInputStream(sbSOAP.toString().getBytes()));
            SOAPPart soapPart = message.getSOAPPart();
            SOAPEnvelope envelope = soapPart.getEnvelope();
            SOAPBody body = envelope.getBody();  
     
            SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();
            SOAPConnection con = factory.createConnection();
            W83bClsTrazas.trazaDebug(null, message.toString());
            SOAPMessage response = con.call(message, this.urlWs);  
            rtdo = W83bBaseWSInterface.getResultado(response);
            W83bClsTrazas.trazaDebug(null, "El resultado de la invocacion del servicio web: " + method + " resultado: " + rtdo);
        }catch(SOAPException e){
        	throw new W83bWSInterfaceException("Error en la invocación del metodo " + method + " del WS" + this.getClass().getName(),e);
        }catch (Exception e) {
        	throw new W83bWSInterfaceException("Error en la invocación del metodo " + method + " del WS" + this.getClass().getName(),e);
		}
        return rtdo;
    }//Fin invoke   	
		/**
		 * Realiza la invocación a un servicio web dada la url, el método los nombres de los parámetros y sus valores
	     * @param method Método del servicio web que se va a invocar
	     * @param paramNames Array de nombres de los parámetros
	     * @param paramValues Array de valores de los parámetros               
	     * @return String con la respuesta del servicio web
	     * @throws W83bWSInterfaceException excepcion
	     */            
			protected  String invoke (String headerEnvelope, String security, String method, String[] paramNames, String[] paramValues) throws W83bWSInterfaceException {
	        String rtdo = "";
	        W83bClsTrazas.trazaDebug(null, "Se invoca el webService: " + method);
		    W83bClsTrazas.trazaDebug(null, "paramNames.length: " + paramNames.length);
	        for(int i=0; i < paramNames.length; i++){
	        	 W83bClsTrazas.trazaDebug(null, "paramName : " + paramNames[i] + " paramValue: " + paramValues[i]); 
	        }
	        try{
	        	 MimeHeaders mimeHeaders = new MimeHeaders();
	        	 mimeHeaders.addHeader("Content-Type", "text/xml");
	        	
	        	
	            MessageFactory mfactory = MessageFactory.newInstance();
	            
	            StringBuffer sbSOAP = new StringBuffer("");
	          

	            sbSOAP.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\""+headerEnvelope+"\">");
	            sbSOAP.append("<soapenv:Header>");
	            sbSOAP.append("<n38>" + security.split("<n38>")[1].split("</n38>")[0] + "</n38>");
	            sbSOAP.append("</soapenv:Header>");
	            sbSOAP.append("<soapenv:Body>");
	            sbSOAP.append("<ws:").append(method).append(">");
	            
	            
	            for (int i=0; i < paramNames.length && i < paramValues.length; i++) {
	 	            sbSOAP.append("<").append(paramNames[i]).append(">");
		            sbSOAP.append(paramValues[i]);
		            sbSOAP.append("</").append(paramNames[i]).append(">");
	            }

	           
	            sbSOAP.append("</ws:").append(method).append(">");
	            sbSOAP.append("</soapenv:Body>");
	            sbSOAP.append("</soapenv:Envelope>");
	            SOAPMessage message = mfactory.createMessage(mimeHeaders,new ByteArrayInputStream(sbSOAP.toString().getBytes()));
	            SOAPPart soapPart = message.getSOAPPart();
	           
	           
	            SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();
	            SOAPConnection con = factory.createConnection();
	             W83bClsTrazas.trazaDebug(null, message.toString());
	            SOAPMessage response = con.call(message, this.urlWs);  
	            rtdo = W83bBaseWSInterface.getResultado(response);
	            W83bClsTrazas.trazaDebug(null, "El resultado de la invocacion del servicio web: " + method + " resultado: " + rtdo);
	        }catch(SOAPException e){
	        	throw new W83bWSInterfaceException("Error en la invocación del metodo " + method + " del WS" + this.getClass().getName(),e);
	        }catch (Exception e) {
	        	throw new W83bWSInterfaceException("Error en la invocación del metodo " + method + " del WS" + this.getClass().getName(),e);
			}
	        return rtdo;
	    }//Fin invoke   	
			
			
			/**
			 * Realiza la invocación a un servicio web dada la url, el método los nombres de los parámetros y sus valores
		     * @param method Método del servicio web que se va a invocar
		     * @param paramNames Array de nombres de los parámetros
		     * @param paramValues Array de valores de los parámetros               
		     * @return String con la respuesta del servicio web
		     * @throws W83bWSInterfaceException excepcion
		     */            
				protected  String invoke (String headerEnvelope, String security, String method, String rootTagName, String rootTagXml) throws W83bWSInterfaceException {
		        String rtdo = "";
		        W83bClsTrazas.trazaDebug(null, "Se invoca el webService: " + method);
			   
		        try{
		        	 MimeHeaders mimeHeaders = new MimeHeaders();
		        	 mimeHeaders.addHeader("Content-Type", "text/xml");
		        	
		        	
		            MessageFactory mfactory = MessageFactory.newInstance();
		            
		            StringBuffer sbSOAP = new StringBuffer("");
		          

		            sbSOAP.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\""+headerEnvelope+"\">");
		            sbSOAP.append("<soapenv:Header>");
		            sbSOAP.append("<n38>" + security.split("<n38>")[1].split("</n38>")[0] + "</n38>");
		            sbSOAP.append("</soapenv:Header>");
		            sbSOAP.append("<soapenv:Body>");
		            sbSOAP.append("<ws:").append(method).append(">");
		            
		            sbSOAP.append("<").append(rootTagName).append(">");
		            sbSOAP.append(rootTagXml);
		            sbSOAP.append("</").append(rootTagName).append(">");
		           
		            sbSOAP.append("</ws:").append(method).append(">");
		            sbSOAP.append("</soapenv:Body>");
		            sbSOAP.append("</soapenv:Envelope>");
		            SOAPMessage message = mfactory.createMessage(mimeHeaders,new ByteArrayInputStream(sbSOAP.toString().getBytes()));
		            SOAPPart soapPart = message.getSOAPPart();
		           
		           
		            SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();
		            SOAPConnection con = factory.createConnection();
		             W83bClsTrazas.trazaDebug(null, message.toString());
		            SOAPMessage response = con.call(message, this.urlWs);  
		            rtdo = W83bBaseWSInterface.getResultado(response);
		             W83bClsTrazas.trazaDebug(null, "El resultado de la invocacion del servicio web: " + method + " resultado: " + rtdo);
		        }catch(SOAPException e){
		        	throw new W83bWSInterfaceException("Error en la invocación del metodo " + method + " del WS" + this.getClass().getName(),e);
		        }catch (Exception e) {
		        	throw new W83bWSInterfaceException("Error en la invocación del metodo " + method + " del WS" + this.getClass().getName(),e);
				}
		        return rtdo;
		    }//Fin invoke   	
		
	
	/**
     * Realiza la invocación a un servicio web dada la url, el método los nombres de los parámetros y sus valores
     * @param method Método del servicio web que se va a invocar
     * @param paramNames Array de nombres de los parámetros
     * @param paramValues Array de valores de los parámetros
     * @param paramAttributes atributos               
     * @return String con la respuesta del servicio web
     * @throws W83bWSInterfaceException excepcion
     */            
		protected  String invoke (String method, String[] paramNames, String[] paramValues, String[] paramAttributes) throws W83bWSInterfaceException {
        String rtdo = "";
         W83bClsTrazas.trazaDebug(null, "Se invoca el webService: " + method);
        for(int i=0; i < paramNames.length; i++){
        	 W83bClsTrazas.trazaDebug(null, "paramName yoly 4: " + paramNames[i] + " paramValue: " + paramValues[i]); 
        }
        try{
            MessageFactory mfactory = MessageFactory.newInstance();
            SOAPMessage message = mfactory.createMessage();
            SOAPPart soapPart = message.getSOAPPart();
            SOAPEnvelope envelope = soapPart.getEnvelope();
            
            envelope.setEncodingStyle("http://schemas.xmlsoap.org/soap/encoding/");
            
            SOAPBody body = envelope.getBody();   
            Name name = envelope.createName(method, "", "http://www.openuri.org/");
            
            SOAPBodyElement element = body.addBodyElement(name);
            for (int i=0; i < paramNames.length && i < paramValues.length; i++) {
                SOAPElement param = element.addChildElement(envelope.createName( paramNames[i]) );
                param.addAttribute(envelope.createName("xsi:type"),"xsd:"+paramAttributes[i]+"" );
                param.addTextNode( paramValues[i] );
            }         
            SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();
            SOAPConnection con = factory.createConnection();
            SOAPMessage response = con.call(message, this.urlWs);  
            rtdo = W83bBaseWSInterface.getResultado(response);
            W83bClsTrazas.trazaDebug(null, "El resultado de la invocacion del servicio web: " + method + " resultado: " + rtdo);
        }catch(SOAPException e){
        	throw new W83bWSInterfaceException("Error en la invocación del metodo " + method + " del WS" + this.getClass().getName(),e);
        }
        
        return rtdo;
    }//Fin invoke   
	
	
		/**
		 * mai
		 * @param args argumentos
		 */
	public static void main(String[] args) {
        try {		
			/* Creamos el mensaje */
			MessageFactory mfactory = MessageFactory.newInstance();
			SOAPMessage message = mfactory.createMessage();
			SOAPPart soapPart = message.getSOAPPart();
			SOAPEnvelope envelope = soapPart.getEnvelope();
	
			/* Cuerpo del mensaje */
			SOAPBody body = envelope.getBody();
					
			envelope.setEncodingStyle("http://schemas.xmlsoap.org/soap/encoding/");
	
			/* Nombre del metodo */	
			Name name = envelope.createName("provincia_getByDesc", "m", "http://www.openuri.org/");
			
			SOAPBodyElement element = body.addBodyElement(name);
	
			/* Parametros del metodo */
			SOAPElement provincias = element.addChildElement(envelope.createName("value"));
			provincias.addAttribute(envelope.createName("xsi:type"),"xsd:string" );
			provincias.addTextNode("");
	
			SOAPElement parents = element.addChildElement(envelope.createName("responseWithParents"));
			/* para mandar un valor null --> parents.addAttribute(envelope.createName("xsi:nil"),"true" ); */
			parents.addAttribute(envelope.createName("xsi:type"),"xsd:boolean" );
			parents.addTextNode("true");
			
			SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();
			SOAPConnection con = factory.createConnection();
			
			
			
			/* Invocamos la llamada */
			SOAPMessage response = con.call(message, "http://www.integracion.jakina.ejiedes.net/t17iApiWSWar/t17iApiWS");
					
			/* Volcando los resultados */
			response.writeTo(System.out);
		       } catch (SOAPException e) {
			
		        } catch (java.io.IOException e) {
			
		        }
     }

	

    /**
     * Devuelve un objeto SOAPBodyElement dado un mensaje SOAP
     * @param response Mensaje SOAP de respuesta          
     * @return SOAPBodyElement Mensaje como objeto SOAPBodyElement
     * @throws SOAPException excepcion SOAP
     */            
    private static SOAPBodyElement getSOAPBodyElement (SOAPMessage response) throws SOAPException {
        SOAPBodyElement rtdo = null;
        Iterator iterator = response.getSOAPPart().getEnvelope().getBody().getChildElements();
        while (iterator.hasNext()) {
            Object oUndefined = iterator.next();
            if (oUndefined instanceof SOAPBodyElement) {
                rtdo = (SOAPBodyElement) oUndefined;
                break;
            }
        }
        return rtdo;
    }//Fin getSOAPBodyElement  
    
    
    /**
     * Devuelve un String dado un mensaje SOAP y reemplaza los tags para capturar la respuesta
     * @param response Mensaje SOAP de respuesta          
     * @return String Mensaje como String
     * @throws SOAPException excepcion SOAP
     */            
    private static String getResultado (SOAPMessage response) throws SOAPException {
    	
        String rtdo = "";        
        SOAPBodyElement soapBodyElement = W83bBaseWSInterface.getSOAPBodyElement(response);    
        //String responseElementName = soapBodyElement.getElementName().toString();        
        //String resultElementName = responseElementName.replaceAll("m:generateDocumentResponse", "Result");          
		
        Iterator iterator = soapBodyElement.getChildElements();               
        while (iterator.hasNext()) {        	
       		Object objElement = iterator.next();
        	if (objElement instanceof SOAPElement) {           	
        		SOAPElement element = (SOAPElement) objElement;
				rtdo = element.getValue();
				if(rtdo==null || "".equals(rtdo)){
					rtdo=element.toString();
				}
				break;
			}
        	if (objElement instanceof weblogic.webservice.core.soap.SOAPElementImpl) {           	
        		weblogic.webservice.core.soap.SOAPElementImpl element = (weblogic.webservice.core.soap.SOAPElementImpl) objElement;
				rtdo = element.getValue();
				break;
			} 
        }        
    	return rtdo;
    }
    
    
    /**
     * Realiza la invocación a un servicio Servlet dada la url, el método los nombres de los parámetros y sus valores
     * @param paramNames Array de nombres de los parámetros
     * @param paramValues Array de valores de los parámetros               
     * @return String con la respuesta del servicio web
     * @throws W83bWSInterfaceException excepcion
     */            
	protected  String invoke (String[] paramNames, String[] paramValues) throws W83bWSInterfaceException {
        String rtdo = "";
       
        HttpClient client = new HttpClient();
        PostMethod method = new PostMethod(this.urlWs);
       
        
        for(int i=0; i < paramNames.length; i++){	        	 
        	method.addParameter(paramNames[i],paramValues[i]);	        	
        	 W83bClsTrazas.trazaDebug(null, "paramName yoly3: " + paramNames[i] + " paramValue: " + paramValues[i]);
        }
         
        W83bClsTrazas.trazaDebug(null, "Se invoca el servlet: " + this.urlWs);
        try {
            // Execute the method.
            int statusCode = client.executeMethod(method);

            if (statusCode != HttpStatus.SC_OK) {
            	throw new W83bWSInterfaceException("Error en la invocacion al servlet: " + method.getStatusLine());
            }

            // Read the response body.
            byte[] responseBody = method.getResponseBody();
            rtdo = new String(responseBody);
            // Deal with the response.
            // Use caution: ensure correct character encoding and is not binary data
           
      } catch (HttpException e) {
    	  throw new W83bWSInterfaceException("Fatal protocol violation: " + e.getMessage(),e);
      } catch (IOException e) {
    	  throw new W83bWSInterfaceException("Fatal transport error: " + e.getMessage(),e);
      } finally {
        // Release the connection.
        method.releaseConnection();
      }  
        
      W83bClsTrazas.trazaDebug(null, "El resultado de la invocacion del servlet: " + this.urlWs + " resultado: " + rtdo);
        
        return rtdo; 
    }
        	
	/**
     * Decide si el retorno del webservice contiene un mensaje de error
     * @param response	SOAPMessage	: Respuesta del WS
     * @return			boolean		: True si contiene un mesaje de error, false e.o.c.
     * @throws SOAPException		: Excepcion SOPAP
     */
    private static boolean hasFault(SOAPMessage response) throws SOAPException{
    	return response.getSOAPPart().getEnvelope().getBody().getFault()!=null;
    }
}
